#pragma once
// 本次改动加入了自定义手写实现序列化与反序列化过程,利用条件编译来进行代码裁剪
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <jsoncpp/json/json.h>
using namespace std;
// #define SELF 1
// 自定义序列化与反序列化分隔符
const string ProtSep = " ";
namespace protocol_ns
{
    const string SEP = "\r\n";
    // 将一个Json串转化为"len"\r\n"{    }"\r\n---添加报头
    // 解决TCP粘包问题
    string Encode(const string &json_str)
    {
        // 获取长度
        int json_str_len = json_str.size();
        // 长度字符串
        string proto_str = to_string(json_str_len);
        // 拼接
        proto_str += SEP;
        proto_str += json_str;
        proto_str += SEP;
        return proto_str;
    }

    // 将一个"len"\r\n"{    }"\r\n做检查并提取出有效信息
    string Decode(string &inbuffer)
    {
        // 拿到分隔符下标
        auto pos = inbuffer.find(SEP);
        if (pos == string::npos)
        {
            //"le"
            return string();
        }
        // 找到了下标"len"\r\n
        // 提取长度字符串
        string len_str = inbuffer.substr(0, pos);
        if (len_str.empty() == true)
        {
            return string();
        }
        int packlen = stoi(len_str); // 拿到报文长度
        // 总报文长度
        int total = len_str.size() + packlen + SEP.size() * 2;
        if (inbuffer.size() < total)
        {
            // 此时inbuffer中没有一个完整报文
            return string();
        }
        // 此时inbuffer中至少是一个完整报文
        // 拿到完整的一个报文
        string package = inbuffer.substr(pos + SEP.size(), packlen);
        // 在inbuffer中将获取到的报文移除
        inbuffer.erase(0, total);
        return package;
    }

    // 请求
    class Request
    {
    public:
        Request() {}
        Request(int x, int y, char oper)
            : _x(x), _y(y), _oper(oper)
        {
        }
        // 序列化
        bool Serialize(string *out)
        {
#ifdef SELF
            //"_x _oper _y"风格
            string data_x = to_string(_x);
            string data_y = to_string(_y);
            string data_str = data_x + ProtSep + _oper + ProtSep + data_y;
            *out = data_str;
            return true;
#else
            Json::Value root;
            root["x"] = _x;
            root["y"] = _y;
            root["oper"] = _oper;
            Json::FastWriter writer;
            *out = writer.write(root);
            return true;
#endif
        }
        // 反序列化
        bool Deserialize(const string &in)
        {
#ifdef SELF
            //"_x _oper _y"风格字符串的解析
            auto left_pos = in.find(ProtSep);
            if (left_pos == string::npos)
            {
                return false;
            }
            auto right_pos = in.rfind(ProtSep);
            if (right_pos == string::npos)
            {
                return false;
            }
            if (left_pos + ProtSep.size() + 1 != right_pos)
            {
                return false;
            }
            string data_x = in.substr(0, left_pos);
            if (data_x.empty() == true)
            {
                return false;
            }
            string data_y = in.substr(right_pos, in.size());
            if (data_y.empty() == true)
            {
                return false;
            }
            _x = stoi(data_x);
            _y = stoi(data_y);
            _oper = in[left_pos + ProtSep.size()];
            return true;
#else
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (res == false)
            {
                return false;
            }
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
            return true;
#endif
        }

    public:
        int _x;     // 操作数
        int _y;     // 操作数
        char _oper; // 操作符号
    };

    // 响应
    class Response
    {
    public:
        Response() {}
        Response(int result, int code)
            : _result(result), _code(code)
        {
        }
        // 序列化
        bool Serialize(string *out)
        {
#ifdef SELF
            //"_result _code"
            string data_result = to_string(_result);
            string data_code = to_string(_code);
            string data_str = data_result + ProtSep + data_code;
            *out = data_str;
            return true;
#else
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;
            Json::FastWriter writer;
            *out = writer.write(root);
            return true;
#endif
        }
        // 反序列化
        bool Deserialize(const string &in)
        {
#ifdef SELF
            //"_result _code"
            auto pos = in.find(ProtSep);
            if (pos == string::npos)
            {
                return false;
            }
            string data_result = in.substr(0, pos);
            if (data_result.empty() == true)
            {
                return false;
            }
            string data_code = in.substr(pos + ProtSep.size(), in.size());
            if (data_code.empty() == true)
            {
                return false;
            }
            _result = stoi(data_result);
            _code = stoi(data_code);
            return true;
#else
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (res == false)
            {
                return false;
            }
            _result = root["result"].asInt();
            _code = root["code"].asInt();
            return true;
#endif
        }

    public:
        int _result; // 结果
        int _code;   // 错误码
    };

    class Factory
    {
    public:
        Factory()
        {
            srand(time(nullptr));
            opers = "+-*/^&|";
        }
        // 构造请求
        shared_ptr<Request> BuildRequest()
        {
            int x = rand() % 10;
            usleep(1000);
            int y = rand() % 5;
            usleep(1000);
            char oper = opers[rand() % opers.size()];
            shared_ptr<Request> req = make_shared<Request>(x, y, oper);
            return req;
        }
        // 将有效信息"len"\r\n"{}"\r\n->Responce
        shared_ptr<Response> BuildResponse()
        {
            return make_shared<Response>();
        }
        ~Factory() {}

    private:
        string opers;
    };

}